home *** CD-ROM | disk | FTP | other *** search
Wrap
/* * CBLibrary - Pal256 * Copyright (C) 2003 Chris Bazley * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* 256 colour selection dialogue */ #include "Pal256.h" /* ANSI library files */ #include <stdlib.h> #include <stdio.h> #include <string.h> /* RISC OS library files */ #include "kernel.h" #include "swis.h" #include "wimp.h" #include "wimplib.h" #include "toolbox.h" #include "event.h" #include "window.h" #include "gadgets.h" /* Other headers */ #include "err.h" #include "msgtrans.h" #include "Macros.h" /* Gadgets */ #define PAL256_CANCEL 0x100 #define PAL256_OK 0x101 #define PAL256_COLOUR 0x105 #define PAL256_PALETTE 0x104 /* Bounding box of area to draw colours */ #define COLOURS_XORIG 28 #define COLOURS_YORIG 104 #define COLOURS_WIDTH 576 #define COLOURS_HEIGHT 576 #define WIN_HEIGHT 708 #ifndef NDEBUG #define OSPLOT(c,x,y) { \ char string[255]; \ sprintf(string, "report OS_Plot action:%d x coord:%d y coord:%d", c, x, y); \ _kernel_oscli(string); \ } \ RE(_swix(OS_Plot, _INR(0,2), c, x, y)) #else #define OSPLOT(c,x,y) RE(_swix(OS_Plot, _INR(0,2), c, x, y)) #endif typedef struct _Pal256Data { ObjectId window_id; /* editing window */ char orig_colnum; /* as specified by client */ char current_colnum; /* as displayed in dialogue */ WimpCaret caretstore; } Pal256Data; extern int palette[256]; extern _kernel_oserror shared_err_block; /* ----------------------------------------------------------------------- */ /* Function prototypes */ static ToolboxEventHandler _Pal256_buttonhandler, _Pal256_deleted; static WimpEventHandler _Pal256_redrawhandler, _Pal256_clickhandler; static _kernel_oserror *_Pal256_disp_colour(Pal256Data *pal_data, char colour_number); /* ----------------------------------------------------------------------- */ /* Public functions */ _kernel_oserror *Pal256_initialise(ObjectId object) { /* Create associated data block */ Pal256Data *pal_data; _kernel_oserror *err; pal_data = malloc(sizeof(Pal256Data)); if(pal_data == NULL) { WRITE_GERR(shared_err_block, "NoMem"); return &shared_err_block; /* failed */ } err = toolbox_set_client_handle(0, object, pal_data); if(err != NULL) goto err_exit; pal_data->window_id = object; pal_data->orig_colnum = 0; pal_data->current_colnum = 0; /* Install handlers */ err = event_register_wimp_handler(object, Wimp_ERedrawWindow, _Pal256_redrawhandler, pal_data); if(err != NULL) goto err_exit; err = event_register_wimp_handler(object, Wimp_EMouseClick, _Pal256_clickhandler, pal_data); if(err != NULL) goto err_exit; err = event_register_toolbox_handler(object, ActionButton_Selected, _Pal256_buttonhandler, pal_data); if(err != NULL) goto err_exit; err = event_register_toolbox_handler(object, Toolbox_ObjectDeleted, _Pal256_deleted, pal_data); if(err != NULL) goto err_exit; return NULL; /* success */ err_exit: free(pal_data); return err; /* failed */ } /* ----------------------------------------------------------------------- */ _kernel_oserror *Pal256_set_colour(ObjectId object, char colour_number) { /* Set the currently selected colour */ Pal256Data *pal_data; THROW(toolbox_get_client_handle(0, object, (void **)&pal_data)); pal_data->orig_colnum = colour_number; /* remember client-specified colour, incase restored by ADJUST-click on Cancel */ return _Pal256_disp_colour(pal_data, colour_number); } /* ----------------------------------------------------------------------- */ /* Private functions */ static _kernel_oserror *_Pal256_disp_colour(Pal256Data *pal_data, char colour_number) { /* Change the displayed colour */ char validation[16]; pal_data->current_colnum = colour_number; sprintf(validation,"r2;c/%X", (palette[colour_number] & 0xffffff00) >> 8); return button_set_validation(0, pal_data->window_id, PAL256_COLOUR, validation); } static int _Pal256_buttonhandler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle) { Pal256Data *pal_data = (Pal256Data *)handle; Pal256ColourSelectedEvent warn_client; NOT_USED(event_code) switch(id_block->self_component) { case PAL256_CANCEL: if(FLAG_SET(event->hdr.flags, ActionButton_Selected_Adjust)) { /* restore default colour as specified by client */ RE(_Pal256_disp_colour(pal_data, pal_data->orig_colnum)) } break; case PAL256_OK: /* Raise event to tell client of colour selection */ warn_client.hdr.size = sizeof(Pal256ColourSelectedEvent); warn_client.hdr.event_code = Pal256_ColourSelected; warn_client.hdr.flags = 0; warn_client.colour_number = pal_data->current_colnum; RE(toolbox_raise_toolbox_event(0, id_block->self_id, -1, (ToolboxEvent *)&warn_client)) pal_data->orig_colnum = pal_data->current_colnum; /* this becomes the new default colour */ default: return 0; /* not interested in this button */ } return 1; /* claim event */ } /* ----------------------------------------------------------------------- */ static int _Pal256_clickhandler(int event_code, WimpPollBlock *event, IdBlock *id_block, void *handle) { /* In order that the pseudo-transient dbox mechanism can work we pass mouse click events on rather than claiming them */ WimpMouseClickEvent *wmce = (WimpMouseClickEvent *)event; NOT_USED(event_code) if(wmce->buttons != Wimp_MouseButtonSelect || id_block->self_component != PAL256_PALETTE) return 0; /* event not handled */ /* Calculate palette origin in screen coordinates */ WimpGetWindowStateBlock winstate; E_RETV(window_get_wimp_handle(0, id_block->self_id, &(winstate.window_handle)), 0) E_RETV(wimp_get_window_state(&winstate), 0) int row = wmce->mouse_y - (winstate.visible_area.ymax - winstate.yscroll - WIN_HEIGHT + COLOURS_YORIG); if(row < 0 || row >= COLOURS_HEIGHT) return 0; /* pass event on */ row /= (COLOURS_HEIGHT/16); int col = wmce->mouse_x - (winstate.visible_area.xmin - winstate.xscroll + COLOURS_XORIG); if(col < 0 || col >= COLOURS_WIDTH) return 0; /* pass event on */ col /= (COLOURS_WIDTH/16); /* Select colour */ RE(_Pal256_disp_colour((Pal256Data *)handle, col + (15-row) * 16)) return 0; /* pass event on */ } /* ----------------------------------------------------------------------- */ static int _Pal256_redrawhandler(int event_code, WimpPollBlock *event, IdBlock *id_block, void *handle) { /* Custom redraw for colour palette */ NOT_USED(event_code) NOT_USED(event) NOT_USED(handle) WimpRedrawWindowBlock block; E_RETV(window_get_wimp_handle(0, id_block->self_id, &block.window_handle), 1) int more; E_RETV(wimp_redraw_window(&block, &more), 1) /* Calculate palette origin in screen coordinates */ int colsleft_scrx = block.visible_area.xmin - block.xscroll + COLOURS_XORIG; int colsbot_scry = block.visible_area.ymax - block.yscroll - WIN_HEIGHT + COLOURS_YORIG; /* N.B. Whilst it would be more logical to have the origin at the top left, this cannot be calculated accurately enough to avoid OS-to-pixel coordinate rounding errors without using the current y eigen factor */ #ifndef NDEBUG { char string[255]; sprintf(string, "report palette origin left:%d bottom:%d", colsleft_scrx, colsbot_scry); _kernel_oscli(string); } #endif while (more) { #ifndef NDEBUG { char string[255]; sprintf(string, "report redraw rectangle xmin:%d ymin:%d xmax:%d ymax:%d", block.redraw_area.xmin, block.redraw_area.ymin, block.redraw_area.xmax, block.redraw_area.ymax); _kernel_oscli(string); } #endif /* Clip redraw area to palette area */ if(block.redraw_area.xmin < colsleft_scrx) block.redraw_area.xmin = colsleft_scrx; if(block.redraw_area.xmax > colsleft_scrx + COLOURS_WIDTH) block.redraw_area.xmax = colsleft_scrx + COLOURS_WIDTH; if(block.redraw_area.ymax > colsbot_scry + COLOURS_HEIGHT) block.redraw_area.ymax = colsbot_scry + COLOURS_HEIGHT; if(block.redraw_area.ymin < colsbot_scry) block.redraw_area.ymin = colsbot_scry; #ifndef NDEBUG { char string[255]; sprintf(string, "report clipped redraw rectangle xmin:%d ymin:%d xmax:%d ymax:%d", block.redraw_area.xmin, block.redraw_area.ymin, block.redraw_area.xmax, block.redraw_area.ymax); _kernel_oscli(string); } #endif /* Calculate rows and columns to draw */ int max_col = block.redraw_area.xmax - colsleft_scrx; if(max_col >= 0) { max_col /= COLOURS_WIDTH/16; if((block.redraw_area.xmax - colsleft_scrx) % (COLOURS_WIDTH/16) == 0) max_col--; /* redraw_area.xmax is exclusive, so don't draw column that coincides exactly with it */ int row = block.redraw_area.ymax - colsbot_scry; if(row >= 0) { row /= COLOURS_HEIGHT/16; if((block.redraw_area.ymax - colsbot_scry) % (COLOURS_HEIGHT/16) == 0) row--; /* redraw_area.ymax is exclusive, so don't draw row that coincides exactly with it */ int min_col = (block.redraw_area.xmin - colsleft_scrx)/(COLOURS_WIDTH/16); int min_row = (block.redraw_area.ymin - colsbot_scry)/(COLOURS_HEIGHT/16); #ifndef NDEBUG { char string[255]; sprintf(string, "report start row:%d end row:%d start col:%d end col:%d", row, min_row, min_col, max_col); _kernel_oscli(string); } #endif /* Draw colour squares */ for(; row >= min_row; row--) { for(int col = min_col; col <= max_col; col++) { RE(_swix(ColourTrans_SetGCOL, _IN(0)|_INR(3,4), palette[col + (15 - row) * 16], /* Set colour */ 0, /* No flags */ 0 /* Replace colour on screen */ )) /* Move, absolute */ OSPLOT(4, colsleft_scrx + col * (COLOURS_WIDTH/16), colsbot_scry + row * (COLOURS_HEIGHT/16)) /* Plot rectangle, relative */ OSPLOT(96+1, COLOURS_WIDTH/16 - 1, COLOURS_HEIGHT/16 - 1) } /* next col */ } /* next row */ } } E_RETV(wimp_get_rectangle(&block, &more), 1) } return 1; /* claim event */ } /* ----------------------------------------------------------------------- */ static int _Pal256_deleted(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle) { /* Remove handlers */ NOT_USED(event_code) NOT_USED(event) RE(event_deregister_toolbox_handler(id_block->self_id, ActionButton_Selected, _Pal256_buttonhandler, handle)) RE(event_deregister_toolbox_handler(id_block->self_id, Toolbox_ObjectDeleted, _Pal256_deleted, handle)) RE(event_deregister_wimp_handler(id_block->self_id, Wimp_ERedrawWindow, _Pal256_redrawhandler, handle)) RE(event_deregister_wimp_handler(id_block->self_id, Wimp_EMouseClick, _Pal256_clickhandler, handle)) return 1; /* claim event */ }